package chord;

public class FingerTable
{
    final static int intChordSize = 16;
    final static int intM = 3;

    Finger[] table = new Finger[intM];
    Node node;

    public void initFingerTable(Node node)
    {
	this.node = node;
	for (int k = 1; k <= intM; k++)
	{
	    table[k - 1] = new Finger();
	    table[k - 1].nodeStart = (node.intID + (int) Math.pow(2, k - 1))
		    % (int) Math.pow(2, intM);
	    table[k - 1].nodeintStartInterval = table[k - 1].nodeStart;
	    table[k - 1].nodeEndInterval = (node.intID + (int) Math.pow(2, k))
		    % (int) Math.pow(2, intM);
	    table[k - 1].nodeSuccessor = node.intID;
	}
    }

    public int findSuccessor(int intNodeID)
    {
	int intSuccessor = intNodeID;

	for (int i = 0; i < intChordSize - 1; i++)
	{
	    intSuccessor++;
	    if (intSuccessor >= intChordSize)
		intSuccessor = 0;

	    // System.out.println("Node Map :" + node.nodeMap);
	    if (node.nodeMap.addrNodes[intSuccessor] != null)
		break;

	}
	return intSuccessor;
    }

    public int findNextSuccessor(int intKeyHash)
    {
	int intNextSuccessor = node.intID;

	for (int i = 0; i < intM; i++)
	{
	    if (isKeyBetween(table[i].nodeintStartInterval,
		    table[i].nodeEndInterval, intKeyHash))
	    {
		intNextSuccessor = table[i].nodeSuccessor;
		break;
	    }

	}
	return intNextSuccessor;
    }

    public int findPredeccessor(int intNodeID)
    {
	int intPredeccessor = intNodeID;

	for (int i = 0; i < intChordSize - 1; i++)
	{
	    intPredeccessor--;
	    if (intPredeccessor < 0)
		intPredeccessor = intChordSize - 1;

	    if (node.nodeMap.addrNodes[intPredeccessor] != null)
		break;
	}
	return intPredeccessor;
    }

    public int findClosestPrecedingNode(int intNodeID)
    {
	int intClosestPrecedingNode = intNodeID;

	for (int i = 0; i < intChordSize - 1; i++)
	{

	    if (intClosestPrecedingNode >= intChordSize)
		intClosestPrecedingNode = 0;

	    if (node.nodeMap.addrNodes[intClosestPrecedingNode] != null)
		break;

	    intClosestPrecedingNode++;
	}
	return intClosestPrecedingNode;
    }

    public void updateFingerTable(int intNewNodeID)
    {
	for (int k = 1; k <= intM; k++)
	{
	    table[k - 1].nodeSuccessor = findClosestPrecedingNode(table[k - 1].nodeStart);
	}
    }

    public void updateOwnFingerTable()
    {
	for (int k = 1; k <= intM; k++)
	{
	    table[k - 1].nodeSuccessor = findClosestPrecedingNode(table[k - 1].nodeStart);
	}
    }

    public boolean isBetween(int intStart, int intEnd, int intNodeID)
    {
	boolean inBet = false;

	if (intEnd < intStart)
	{
	    if (intNodeID > intStart && intNodeID < intChordSize)
		inBet = true;
	    else if (intNodeID >= 0 && intNodeID <= intEnd)
		inBet = true;
	}
	else
	{
	    if (intNodeID > intStart && intNodeID <= intEnd)
		inBet = true;

	}
	return inBet;
    }

    public boolean isKeyBetween(int intStart, int intEnd, int intSearchKey)
    {
	boolean inBet = false;

	if (intEnd < intStart)
	{
	    if (intSearchKey >= intStart && intSearchKey < intChordSize)
		inBet = true;
	    else if (intSearchKey >= 0 && intSearchKey < intEnd)
		inBet = true;
	}
	else
	{
	    if (intSearchKey >= intStart && intSearchKey < intEnd)
		inBet = true;

	}

	Logger.log(LogType.RAW, "isKeyBetween" + intStart + "  " + intEnd
		+ "  " + intSearchKey + "  " + inBet);

	return inBet;
    }

    public boolean isKeyLessThanNextSuccessor(int intSearchKey)
    {
	boolean inBet = false;

	Logger.log(LogType.RAW, "isKeyLessThanNextSuccessor");

	for (int i = 0; i < intM; i++)
	{
	    if (isKeyBetween(table[i].nodeintStartInterval,
		    table[i].nodeEndInterval, intSearchKey))
	    {
		if (isKeyBetween(table[i].nodeintStartInterval,
			table[i].nodeSuccessor, intSearchKey))
		    inBet = true;
		break;
	    }

	}
	return inBet;
    }

    public void show()
    {
	Logger.log(LogType.RAW,
		"Start \t Interval(start) \t Interval(end) \t Successor");

	for (int k = 1; k <= intM; k++)
	{
	    Logger.log(LogType.RAW, table[k - 1].nodeStart + " \t "
		    + table[k - 1].nodeintStartInterval + " \t "
		    + table[k - 1].nodeEndInterval + " \t "
		    + table[k - 1].nodeSuccessor);
	}
    }
}
